package vn.bus.bk.map;

import java.util.ArrayList;

import vn.bus.bk.R;
import vn.bus.bk.object.BusInfo;
import android.content.Context;
import android.content.Intent;
import android.graphics.Color;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.provider.Settings;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.ImageView;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragmentActivity;
import com.actionbarsherlock.view.MenuItem;
import com.google.android.gms.common.GooglePlayServicesNotAvailableException;
import com.google.android.gms.maps.CameraUpdate;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.MapsInitializer;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.GoogleMap.OnCameraChangeListener;
import com.google.android.gms.maps.model.BitmapDescriptorFactory;
import com.google.android.gms.maps.model.CameraPosition;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.LatLngBounds;
import com.google.android.gms.maps.model.MarkerOptions;
import com.google.android.gms.maps.model.PolylineOptions;

public class BusMap extends SherlockFragmentActivity {

    public static BusInfo myBus;
    private GoogleMap gMap;
    private LatLngBounds.Builder bc;
    private boolean isError = false;
    private ImageView updateLocation;

    private LocationManager locationManager;
    private LocationListener locationListener;
    private double longitude;
    private double latitude;

    private boolean isFinded = false;

    public static final int LOCATION = Menu.FIRST + 2;

    public static final long MINIMUM_DISTANCE_CHANGE_FOR_UPDATES = 1; // in
    // Meters
    public static final long MINIMUM_TIME_BETWEEN_UPDATES = 1000; // in

    @Override
    public void onCreate(Bundle savedInstanceState) {
	super.onCreate(savedInstanceState);
	setContentView(R.layout.map);
	getSupportActionBar().setDisplayHomeAsUpEnabled(true);
	getSupportActionBar().setHomeButtonEnabled(true);
	try {
	    MapsInitializer.initialize(getApplicationContext());
	} catch (GooglePlayServicesNotAvailableException e) {
	    // TODO Auto-generated catch block
	    e.printStackTrace();
	}

	updateLocation = (ImageView) findViewById(R.id.img_update_location);

	updateLocation.setOnClickListener(new OnClickListener() {

	    @Override
	    public void onClick(View v) {
		detectLocation();
		drawLocation();
	    }
	});

	gMap = ((SupportMapFragment) getSupportFragmentManager()
		.findFragmentById(R.id.map)).getMap();
	bc = new LatLngBounds.Builder();
	setTitle(myBus.getName());
	getSupportActionBar().setDisplayHomeAsUpEnabled(true);
	getSupportActionBar().setHomeButtonEnabled(true);
	convertToArrayPoint();
	if (!isError) {
	    final CameraUpdate cameraUpdate = CameraUpdateFactory
		    .newLatLngBounds(bc.build(), 45);

	    gMap.setOnCameraChangeListener(new OnCameraChangeListener() {

		@Override
		public void onCameraChange(CameraPosition arg0) {
		    // TODO Auto-generated method stub

		    gMap.moveCamera(cameraUpdate);
		    gMap.animateCamera(cameraUpdate);
		    gMap.setOnCameraChangeListener(null);
		}
	    });
	}
    }

    private void convertToArrayPoint() {

	String ordinateGo = myBus.getOrdinateGo();
	String[] arrayGo = ordinateGo.split(",");

	ArrayList<LatLng> latLngGo = new ArrayList<LatLng>();
	for (int i = 0; i < arrayGo.length - 1; i += 2) {
	    try {
		Log.i("STATE", "updateGo" + String.valueOf(i) + " "
			+ arrayGo[i] + "    " + arrayGo[i + 1]);
		double latitude = Double.parseDouble(arrayGo[i]);
		double longitude = Double.parseDouble(arrayGo[i + 1]);
		LatLng latLng = new LatLng(latitude, longitude);
		latLngGo.add(latLng);
		bc.include(latLng);
	    } catch (NumberFormatException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		Toast.makeText(BusMap.this, "Error in update data",
			Toast.LENGTH_SHORT).show();
		isError = true;
		break;
	    }
	}
	if (!isError) {
	    for (int i = 0; i < latLngGo.size() - 1; i++) {
		gMap.addPolyline(new PolylineOptions()
			.add(latLngGo.get(i), latLngGo.get(i + 1)).width(8)
			.color(Color.BLUE).geodesic(true));
	    }
	}

	String ordinateBack = myBus.getOrdinateBack();
	String[] arrayBack = ordinateBack.split(",");
	ArrayList<LatLng> latLngBack = new ArrayList<LatLng>();
	for (int i = 0; i < arrayBack.length - 1; i += 2) {
	    try {

		double latitude = Double.parseDouble(arrayBack[i]);
		double longitude = Double.parseDouble(arrayBack[i + 1]);
		Log.i("STATE", "updateBack" + String.valueOf(latitude));
		LatLng latLng = new LatLng(latitude, longitude);
		latLngBack.add(latLng);
		bc.include(latLng);
	    } catch (NumberFormatException e) {
		// TODO Auto-generated catch block
		e.printStackTrace();
		Toast.makeText(BusMap.this, "Error in update data",
			Toast.LENGTH_SHORT).show();
		isError = true;
		break;
	    }
	}
	if (!isError) {
	    for (int i = 0; i < latLngBack.size() - 1; i++) {
		gMap.addPolyline(new PolylineOptions()
			.add(latLngBack.get(i), latLngBack.get(i + 1)).width(8)
			.color(Color.RED).geodesic(true));
	    }
	}

    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
	if (item.getItemId() == android.R.id.home) {
	    finish();
	}
	return super.onOptionsItemSelected(item);
    }

    private void drawLocation() {
	// TODO Auto-generated method stub
	Log.i("FINDED", String.valueOf(isFinded));
	if (isFinded) {
	    LatLng myPosition = new LatLng(latitude, longitude);
	    gMap.addMarker(new MarkerOptions().position(myPosition).icon(
		    BitmapDescriptorFactory.fromResource(R.drawable.ic_mine)));
	    final CameraUpdate cameraUpdate = CameraUpdateFactory
		    .newCameraPosition(new CameraPosition(myPosition, 15, 0, 0));
	    gMap.animateCamera(cameraUpdate);
	    gMap.setOnCameraChangeListener(new OnCameraChangeListener() {

		@Override
		public void onCameraChange(CameraPosition arg0) {
		    // TODO Auto-generated method stub

		    gMap.moveCamera(cameraUpdate);
		    gMap.animateCamera(cameraUpdate);
		    gMap.setOnCameraChangeListener(null);
		}
	    });
	}
    }

    private void detectLocation() {
	locationManager = (LocationManager) this
		.getSystemService(Context.LOCATION_SERVICE);

	locationListener = new LocationListener() {

	    @Override
	    public void onStatusChanged(String arg0, int arg1, Bundle arg2) {

	    }

	    @Override
	    public void onProviderEnabled(String arg0) {
	    }

	    @Override
	    public void onProviderDisabled(String arg0) {

	    }

	    @Override
	    public void onLocationChanged(Location location) {
		// TODO Auto-generated method stub

	    }

	};

	locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER,
		MINIMUM_TIME_BETWEEN_UPDATES,
		MINIMUM_DISTANCE_CHANGE_FOR_UPDATES, locationListener);
	if (locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
	    findNetwork();

	} else if (locationManager
		.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
	    findGPS();
	} else {

	    enableLocationSettings();

	}
    }

    private void findNetwork() {
	Log.i("LOCATION", "NETWORK");
	try {
	    locationManager.requestLocationUpdates(
		    LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);
	    Location lastKnowLocation = locationManager
		    .getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
	    if (lastKnowLocation != null) {
		setGeoLocation(lastKnowLocation);
	    } else {
		Toast.makeText(this,
			"Cannot find network location, find via GPS",
			Toast.LENGTH_SHORT).show();

		if (locationManager
			.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
		    findGPS();
		}
	    }
	} catch (IllegalArgumentException e) {
	    e.printStackTrace();
	}
    }

    private void findGPS() {
	Log.i("LOCATION", "GPS");
	try {
	    locationManager.requestLocationUpdates(
		    LocationManager.GPS_PROVIDER, 0, 0, locationListener);

	    Location lastKnowLocation = locationManager
		    .getLastKnownLocation(LocationManager.GPS_PROVIDER);
	    if (lastKnowLocation != null) {
		Log.v("TEST", "last lat: " + lastKnowLocation.getLatitude());
		setGeoLocation(lastKnowLocation);

	    }
	} catch (IllegalArgumentException e) {
	    Toast.makeText(
		    this,
		    "Your device does not support GPS Provider! Try NETWORK Provider.",
		    Toast.LENGTH_SHORT).show();
	}
    }

    private void enableLocationSettings() {
	Intent settingsIntent = new Intent(
		Settings.ACTION_LOCATION_SOURCE_SETTINGS);
	startActivity(settingsIntent);
    }

    private void setGeoLocation(Location location) {
	latitude = location.getLatitude();
	longitude = location.getLongitude();
	Log.i("lat", String.valueOf(latitude));
	Log.i("long", String.valueOf(longitude));
	isFinded = true;
    }

}
